<script setup>
// 1引入three.js
import * as THREE from "three";
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
// 2、创建一个3维场景Scene; 你可以把三维场景Scene (opens new window)对象理解为虚拟的3D场景，用来表示模拟生活中的真实三维场景,或者说三维世界。
const scene = new THREE.Scene();
// 3、创建一个长方体的集合对象Geometry
// 设置几何体长宽高，也就是x、y、z三个方向的尺寸
//对比三个参数分别对应xyz轴哪个方向
const geometry = new THREE.BoxGeometry(100, 60, 20);
// 4、定义物体外观（材质）；不同材质渲染出来的效果不同 MeshBasicMaterial: 网格基础材质
const material = new THREE.MeshLambertMaterial({
  color: 0x0000ff, //0xff0000设置材质颜色为红色
  transparent: true, //++++++ 开启透明
  opacity: 0.5, //++++++ 设置透明度
});
// 5、物体：网格模型Mesh； 实际生活中有各种各样的物体，在threejs中可以通过网格模型mesh表示一个虚拟的物体，比如一个箱子，一个鼠标
const mesh = new THREE.Mesh(geometry, material); // 网格模型对象Mesh: 两个参数分别为几何体geometry、材质material
// 6、模型位置.position  实际生活中，一个物体往往是有位置的，对于threejs而言也是一样的，你可以通过位置属性.position定义网格模型Mesh在三维场景Scene中的位置。
//设置网格模型在三维空间中的位置坐标，默认是坐标原点

// 7、.add()方法 在threejs中你创建了一个表示物体的虚拟对象Mesh，需要通过.add()方法，把网格模型mesh添加到三维场景scene中。
scene.add(mesh);
mesh.position.set(100, 0, 0);

// +++++ 辅助观察坐标系: THREE.AxesHelper()的参数表示坐标系坐标轴线段尺寸大小，你可以根据需要改变尺寸。
// AxesHelper的xyz轴
// three.js坐标轴颜色红R、绿G、蓝B分别对应坐标系的x、y、z轴，对于three.js的3D坐标系默认y轴朝上。
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

// 点状光
// const pointLight = new THREE.PointLight(0xffffff, 5.0);
// pointLight.position.set(100, 60, 50);
// scene.add(pointLight);

// 环境光 环境光AmbientLight (opens new window)没有特定方向，只是整体改变场景的光照明暗。
// const pointLight = new THREE.AmbientLight(0xffffff, 5.0);
// pointLight.position.set(100, 60, 50);
// scene.add(pointLight);

// 平行光 平行光DirectionalLight (opens new window)就是沿着特定方向发射。
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源的方向：通过光源position属性和目标指向对象的position属性计算
directionalLight.position.set(100, 60, 50);
// 方向光指向对象网格模型mesh，可以不设置，默认的位置是0,0,0
directionalLight.target = mesh;
scene.add(directionalLight);

// 点状光 添加辅助光源
// const pointLightHelper = new THREE.PointLightHelper(directionalLight, 10);
// scene.add(pointLightHelper);

// DirectionalLightHelper：可视化平行光
const dirLightHelper = new THREE.DirectionalLightHelper(
  directionalLight,
  5,
  0xff0000
);
scene.add(dirLightHelper);

// 8、透视投影相机PerspectiveCamera
// Threejs提供了正投影相机OrthographicCamera (opens new window)和透视投影相机PerspectiveCamera (opens new window)。本节课先给大家比较常用的透视投影相机PerspectiveCamera。
// 透视投影相机PerspectiveCamera本质上就是在模拟人眼观察这个世界的规律。
const camera = new THREE.PerspectiveCamera(
  30, // 垂直方向的观察角度
  window.innerWidth / window.innerHeight, // 观察百分百 width / height
  0.1, // 相机视锥体近裁截面相对相机距离	0.1
  2000 // 相机视锥体远裁截面相对相机距离，far-near构成了视锥体高度方向	2000
);

// 9、相机位置.position
// 生活中用相机拍照，你相机位置不同，拍照结果也不同，threejs中虚拟相机同样如此。
// 比如有一间房子，你拿着相机站在房间里面，看到的是房间内部，站在房子外面看到的是房子外面效果。
// 相机对象Camera具有位置属性.position，通过位置属性.position可以设置相机的位置。

//相机在Three.js三维坐标系中的位置
// 根据需要设置相机位置具体值
camera.position.set(-1000, 0, 0);

// 10、相机观察目标.lookAt()
// 你用相机拍照你需要控制相机的拍照目标，具体说相机镜头对准哪个物体或说哪个坐标。对于threejs相机而言，就是设置.lookAt()方法的参数，指定一个3D坐标。

//相机观察目标指向Threejs 3D空间中某个位置
// camera.lookAt(0, 0, 0); //坐标原点

// camera.lookAt(0, 10, 0);  //y轴上位置10

camera.lookAt(mesh.position); //指向mesh对应的位置
// PerspectiveCamera参数介绍：PerspectiveCamera( fov, aspect, near, far )

// 参数	含义	默认值
// fov	相机视锥体竖直方向视野角度	50
// aspect	相机视锥体水平方向和竖直方向长度比，一般设置为Canvas画布宽高比width / height	1
// near	相机视锥体近裁截面相对相机距离	0.1
// far	相机视锥体远裁截面相对相机距离，far-near构成了视锥体高度方向	2000

// 11、WebGL渲染器WebGLRenderer； 通过WebGL渲染器WebGLRenderer (opens new window)可以实例化一个WebGL渲染器对象。
const renderer = new THREE.WebGLRenderer();
// +++++++++++++++++++++++++++++++++++++++++
// #使用OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
controls.addEventListener("change", function () {
  renderer.render(scene, camera); //执行渲染操作
}); //监听鼠标、键盘事件
// OrbitControls本质;
// OrbitControls本质上就是改变相机的参数，比如相机的位置属性，改变相机位置也可以改变相机拍照场景中模型的角度，实现模型的360度旋转预览效果，改变透视投影相机距离模型的距离，就可以改变相机能看到的视野范围。
// +++++++++++++++++++++++++++++++++++++++++
// 12、设置Canvas画布尺寸.setSize()
renderer.setSize(window.innerWidth, window.innerHeight);
// 13、渲染器渲染方法.render()
// 渲染器WebGLRenderer执行渲染方法.render()就可以生成一个Canvas画布(照片)，并把三维场景Scene呈现在canvas画布上面,你可以把.render()理解为相机的拍照动作“咔”
renderer.render(scene, camera); // 执行渲染操作
// 14、渲染器Canvas画布属性.domElement
// 渲染器WebGLRenderer通过属性.domElement可以获得渲染方法.render()生成的Canvas画布，.domElement本质上就是一个HTML元素：Canvas画布。
document.body.append(renderer.domElement);
</script>
<template>
  <div></div>
</template>
